/*
 * Zed Attack Proxy (ZAP) and its related class files.
 *
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Please note that this file was originally released under the
 * GNU General Public License as published by the Free Software Foundation;
 * either version 2 of the License, or (at your option) any later version
 * by Compass Security AG.
 *
 * As of October 2014 Compass Security AG granted the OWASP ZAP Project
 * permission to redistribute this code under the Apache License, Version 2.0.
 */
package ch.csnc.extension.ui;

import ch.csnc.extension.util.DriverConfiguration;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.LayoutStyle;
import javax.swing.SwingConstants;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.model.Model;
import org.parosproxy.paros.view.AbstractFrame;
import org.zaproxy.zap.utils.ZapTextField;

public class DriversView extends AbstractFrame {

    private static final long serialVersionUID = -7502331281272992501L;

    private DriverTableModel driverTableModel;
    private JTable driverTable;

    private JButton addButton;
    private JButton browseButton;
    private JButton closeButton;
    private JButton deleteButton;

    private JScrollPane driverScrollPane;

    private JLabel fileLabel;
    private ZapTextField fileTextField;

    private JLabel nameLabel;
    private ZapTextField nameTextField;

    private JLabel slotLabel;
    private ZapTextField slotTextField;

    private JLabel slotListIndexLabel;
    private ZapTextField slotListIndexTextField;

    /**
     * Creates new form Drivers
     *
     * @param driverConfig
     */
    public DriversView(DriverConfiguration driverConfig) {
        this.driverTableModel = new DriverTableModel(driverConfig);
        initComponents();
        setVisible(true);
    }

    /**
     * This method is called from within the constructor to initialize the form. WARNING: Do NOT
     * modify this code. The content of this method is always regenerated by the Form Editor.
     */
    private void initComponents() {
        fileLabel = new JLabel();
        fileTextField = new ZapTextField();
        browseButton = new JButton();
        nameLabel = new JLabel();
        nameTextField = new ZapTextField();
        slotLabel = new JLabel();
        slotTextField = new ZapTextField();
        slotListIndexLabel = new JLabel();
        slotListIndexTextField = new ZapTextField();
        addButton = new JButton();
        deleteButton = new JButton();
        closeButton = new JButton();
        driverScrollPane = new JScrollPane();
        driverTable = new JTable();

        setTitle(Constant.messages.getString("certificates.pkcs11.drivers.title"));
        fileLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.path"));

        browseButton.setText(
                Constant.messages.getString("certificates.pkcs11.drivers.button.browse"));
        browseButton.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent evt) {
                        browseButtonActionPerformed(evt);
                    }
                });

        nameLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.name"));

        slotLabel.setText(Constant.messages.getString("certificates.pkcs11.drivers.label.slot"));

        slotListIndexLabel.setText(
                Constant.messages.getString("certificates.pkcs11.drivers.label.slotIndex"));

        addButton.setText(Constant.messages.getString("certificates.pkcs11.drivers.button.add"));
        addButton.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent evt) {
                        addButtonActionPerformed(evt);
                    }
                });

        deleteButton.setText(
                Constant.messages.getString("certificates.pkcs11.drivers.button.delete"));
        deleteButton.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent evt) {
                        deleteButtonActionPerformed(evt);
                    }
                });

        closeButton.setText(
                Constant.messages.getString("certificates.pkcs11.drivers.button.close"));
        closeButton.addActionListener(
                new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent evt) {
                        closeButtonActionPerformed(evt);
                    }
                });

        driverTable.setModel(driverTableModel);
        driverScrollPane.setViewportView(driverTable);

        // When experimental SlotListIndex support is used, the slotTextField is disabled (and vice
        // versa),
        // as only one of these parameters is actually used.
        if (!Model.getSingleton()
                .getOptionsParam()
                .getExperimentalFeaturesParam()
                .isExerimentalSliSupportEnabled()) {
            slotTextField.setEnabled(false);
        }

        final GroupLayout layout = new GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                        .addGroup(
                                layout.createSequentialGroup()
                                        .addContainerGap()
                                        .addGroup(
                                                layout.createParallelGroup(
                                                                GroupLayout.Alignment.LEADING)
                                                        .addComponent(fileLabel)
                                                        .addComponent(nameLabel)
                                                        .addComponent(slotLabel)
                                                        .addComponent(slotListIndexLabel)
                                                        .addGroup(
                                                                layout.createSequentialGroup()
                                                                        .addGroup(
                                                                                layout.createParallelGroup(
                                                                                                GroupLayout
                                                                                                        .Alignment
                                                                                                        .TRAILING,
                                                                                                false)
                                                                                        .addComponent(
                                                                                                nameTextField,
                                                                                                GroupLayout
                                                                                                        .Alignment
                                                                                                        .LEADING)
                                                                                        .addComponent(
                                                                                                slotTextField,
                                                                                                GroupLayout
                                                                                                        .Alignment
                                                                                                        .LEADING)
                                                                                        .addComponent(
                                                                                                slotListIndexTextField,
                                                                                                GroupLayout
                                                                                                        .Alignment
                                                                                                        .LEADING)
                                                                                        .addComponent(
                                                                                                fileTextField,
                                                                                                GroupLayout
                                                                                                        .Alignment
                                                                                                        .LEADING,
                                                                                                GroupLayout
                                                                                                        .DEFAULT_SIZE,
                                                                                                322,
                                                                                                Short
                                                                                                        .MAX_VALUE))
                                                                        .addPreferredGap(
                                                                                LayoutStyle
                                                                                        .ComponentPlacement
                                                                                        .RELATED)
                                                                        .addGroup(
                                                                                layout.createParallelGroup(
                                                                                                GroupLayout
                                                                                                        .Alignment
                                                                                                        .LEADING)
                                                                                        .addComponent(
                                                                                                addButton,
                                                                                                GroupLayout
                                                                                                        .DEFAULT_SIZE,
                                                                                                80,
                                                                                                Short
                                                                                                        .MAX_VALUE)
                                                                                        .addComponent(
                                                                                                browseButton))))
                                        .addContainerGap(165, Short.MAX_VALUE))
                        .addGroup(
                                GroupLayout.Alignment.TRAILING,
                                layout.createSequentialGroup()
                                        .addGap(499, 499, 499)
                                        .addComponent(
                                                closeButton,
                                                GroupLayout.DEFAULT_SIZE,
                                                74,
                                                Short.MAX_VALUE)
                                        .addContainerGap())
                        .addGroup(
                                layout.createSequentialGroup()
                                        .addContainerGap()
                                        .addComponent(
                                                driverScrollPane,
                                                GroupLayout.DEFAULT_SIZE,
                                                561,
                                                Short.MAX_VALUE)
                                        .addContainerGap())
                        .addGroup(
                                GroupLayout.Alignment.TRAILING,
                                layout.createSequentialGroup()
                                        .addContainerGap(499, Short.MAX_VALUE)
                                        .addComponent(deleteButton)
                                        .addContainerGap()));
        layout.setVerticalGroup(
                layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                        .addGroup(
                                GroupLayout.Alignment.TRAILING,
                                layout.createSequentialGroup()
                                        .addContainerGap()
                                        .addComponent(fileLabel)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(
                                                layout.createParallelGroup(
                                                                GroupLayout.Alignment.LEADING,
                                                                false)
                                                        .addComponent(
                                                                browseButton, 0, 0, Short.MAX_VALUE)
                                                        .addComponent(fileTextField))
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(nameLabel)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(
                                                layout.createParallelGroup(
                                                                GroupLayout.Alignment.BASELINE)
                                                        .addComponent(
                                                                nameTextField,
                                                                GroupLayout.PREFERRED_SIZE,
                                                                GroupLayout.DEFAULT_SIZE,
                                                                GroupLayout.PREFERRED_SIZE))
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(slotLabel)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(
                                                layout.createParallelGroup(
                                                                GroupLayout.Alignment.BASELINE)
                                                        .addComponent(
                                                                slotTextField,
                                                                GroupLayout.PREFERRED_SIZE,
                                                                GroupLayout.DEFAULT_SIZE,
                                                                GroupLayout.PREFERRED_SIZE))
                                        .addGap(28, 28, 28)
                                        .addComponent(slotListIndexLabel)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addGroup(
                                                layout.createParallelGroup(
                                                                GroupLayout.Alignment.BASELINE)
                                                        .addComponent(
                                                                slotListIndexTextField,
                                                                GroupLayout.PREFERRED_SIZE,
                                                                GroupLayout.DEFAULT_SIZE,
                                                                GroupLayout.PREFERRED_SIZE)
                                                        .addComponent(
                                                                addButton,
                                                                GroupLayout.PREFERRED_SIZE,
                                                                19,
                                                                GroupLayout.PREFERRED_SIZE))
                                        .addGap(28, 28, 28)
                                        .addComponent(
                                                driverScrollPane,
                                                GroupLayout.PREFERRED_SIZE,
                                                195,
                                                GroupLayout.PREFERRED_SIZE)
                                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(deleteButton)
                                        .addPreferredGap(
                                                LayoutStyle.ComponentPlacement.RELATED,
                                                9,
                                                Short.MAX_VALUE)
                                        .addComponent(
                                                closeButton,
                                                GroupLayout.PREFERRED_SIZE,
                                                10,
                                                GroupLayout.PREFERRED_SIZE)
                                        .addContainerGap()));

        layout.linkSize(
                SwingConstants.VERTICAL,
                new Component[] {
                    addButton, browseButton, closeButton, deleteButton, fileTextField, nameTextField
                });

        for (int i = 0; i < driverTableModel.getColumnCount(); i++) {
            driverTable
                    .getColumnModel()
                    .getColumn(i)
                    .setPreferredWidth(driverTableModel.getPreferredWith(i));
        }

        pack();
    }

    private void browseButtonActionPerformed(ActionEvent evt) {
        final JFileChooser fc = new JFileChooser();
        // TODO Support so and dynlib files as well
        fc.setFileFilter(new FileNameExtensionFilter("DLL/dylib", "dll", "dylib"));

        final int state = fc.showOpenDialog(null);

        if (state == JFileChooser.APPROVE_OPTION) {
            fileTextField.setText(fc.getSelectedFile().toString());
        }
    }

    private void addButtonActionPerformed(ActionEvent evt) {
        final String name = nameTextField.getText();
        final String file = fileTextField.getText();
        int slot = -1;
        int slotListindex = -1;
        try {
            slot = Integer.parseInt(slotTextField.getText());
        } catch (final Exception e) {
            slotTextField.setText("0");
        }
        try {
            slotListindex = Integer.parseInt(slotListIndexTextField.getText());
        } catch (final Exception e) {
            slotListIndexTextField.setText("0");
        }

        if (name != null
                && name.trim().length() > 0
                && file != null
                && file.trim().length() > 0
                && slot > -1
                && slotListindex > -1) {
            driverTableModel.addDriver(name, file, slot, slotListindex);

            nameTextField.setText("");
            fileTextField.setText("");
            slotTextField.setText("0");
            slotListIndexTextField.setText("0");
        }
    }

    private void deleteButtonActionPerformed(ActionEvent evt) {
        final int selrow = driverTable.getSelectedRow();
        if (selrow > -1) {
            driverTableModel.deleteDriver(selrow);

            nameTextField.setText("");
            fileTextField.setText("");
            slotTextField.setText("0");
            slotListIndexTextField.setText("0");
        }
    }

    private void closeButtonActionPerformed(ActionEvent evt) {
        setVisible(false);
        dispose();
    }
}
